package cn.itcast.hotel.service.impl;

import cn.itcast.hotel.constant.EsConstant;
import cn.itcast.hotel.mapper.HotelMapper;
import cn.itcast.hotel.pojo.Hotel;
import cn.itcast.hotel.pojo.HotelDoc;
import cn.itcast.hotel.pojo.dto.HotelDocDto;
import cn.itcast.hotel.service.IHotelService;
import cn.itcast.hotel.utils.ResultUtil;
import cn.itcast.hotel.utils.SearchConditionUtil;
import cn.itcast.hotel.web.result.PageResult;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;

import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * hotel业务层接口实现类
 *
 * @author xiaojiangshi
 */
@Service
public class HotelServiceImpl extends ServiceImpl<HotelMapper, Hotel> implements IHotelService {

    @Autowired
    private RestHighLevelClient client;

    /**
     * 根据条件分页查询
     *
     * @param hotelDocDto 前端传来的分页数据
     * @return 结果返回对象
     */
    @Override
    public PageResult<HotelDoc> listByCondition(HotelDocDto hotelDocDto) {
        //新建分页结果集对象，参数为空
        PageResult<HotelDoc> result = new PageResult<>();
        try {
            //1、创建request对象
            SearchRequest request = new SearchRequest(EsConstant.INDEX);
            //2、从前端对象中取出参数
            Integer page = hotelDocDto.getPage();
            Integer size = hotelDocDto.getSize();
            //3、添加条件，进行筛选
            SearchConditionUtil.boolSearch(request, hotelDocDto);
            //4、进行分页查询
            request.source().from((page - 1) * size).size(size);

            String location = hotelDocDto.getLocation();
            if (location != null) {
                request.source().sort(SortBuilders.geoDistanceSort("location", new GeoPoint(location))
                        .order(SortOrder.ASC).unit(DistanceUnit.KILOMETERS));
            }

            //5、发送请求，获得响应
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            //6、对响应数据，进行解析，得到结果
            result = ResultUtil.resultUtil(response);

        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 根据条件查询
     *
     * @param hotelDocDto 条件数据
     * @return map对象
     */
    @Override
    public Map<String, List<String>> filterByCondition(HotelDocDto hotelDocDto) {
        Map<String, List<String>> result = new HashMap<>();
        try {
            //创建request对象
            SearchRequest request = new SearchRequest(EsConstant.INDEX);
            //添加条件进行筛选
            SearchConditionUtil.boolSearch(request, hotelDocDto);
            //聚合
            SearchConditionUtil.addAgg(request, "brandAgg", "brand", 10);
            SearchConditionUtil.addAgg(request, "starNameAgg", "starName", 10);
            SearchConditionUtil.addAgg(request, "cityAgg", "city", 10);
            //发送请求，获得响应
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            //处理聚合响应结果
            List<String> brandAgg = ResultUtil.getAggListResult(response, "brandAgg");
            result.put("brand", brandAgg);

            List<String> starNameAgg = ResultUtil.getAggListResult(response, "starNameAgg");
            result.put("starName", starNameAgg);

            List<String> cityAgg = ResultUtil.getAggListResult(response, "cityAgg");
            result.put("city", cityAgg);

        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 根据id删除es
     *
     * @param id hotel id
     */
    @Override
    public void deleteById(Long id) {
        try {
            DeleteRequest request = new DeleteRequest(EsConstant.INDEX, id.toString());
            client.delete(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据id修改或者新增es
     *
     * @param id hotel id
     */
    @Override
    public void insertById(Long id) {
        try {
            Hotel hotel = this.getById(id);
            HotelDoc hotelDoc = new HotelDoc(hotel);

            IndexRequest request = new IndexRequest(EsConstant.INDEX).id(hotelDoc.getId().toString());

            request.source(JSON.toJSONString(hotelDoc), XContentType.JSON);

            client.index(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


}
